<template>
  <div class="register-container">
    <div class="register-wrapper">
      <h2 class="register-title">账号注册</h2>
      
      <!-- 步骤指示器 -->
      <div class="step-indicator">
        <div class="step-item" :class="{ active: currentStep === 1, completed: currentStep > 1 }">
          <div class="step-number">{{ currentStep > 1 ? '✓' : '1' }}</div>
          <div class="step-text">验证手机</div>
        </div>
        <div class="step-line" :class="{ active: currentStep > 1 }"></div>
        <div class="step-item" :class="{ active: currentStep === 2, completed: currentStep > 2 }">
          <div class="step-number">{{ currentStep > 2 ? '✓' : '2' }}</div>
          <div class="step-text">填写账号信息</div>
        </div>
        <div class="step-line" :class="{ active: currentStep > 2 }"></div>
        <div class="step-item" :class="{ active: currentStep === 3 }">
          <div class="step-number">3</div>
          <div class="step-text">注册成功</div>
        </div>
      </div>

      <!-- 步骤1：验证手机号 -->
        <el-form v-if="currentStep === 1" ref="phoneFormRef" :model="phoneForm" :rules="phoneRules" class="register-form">
          <!-- 手机号输入框 -->
          <el-form-item prop="phone">
            <div class="phone-input-wrapper">
              <div class="country-code-container">
                <span class="country-code">中国 0086</span>
              </div>
<!-- Slots​
插槽名	说明
prefix	输入框头部内容，只对非 type="textarea" 有效
suffix	输入框尾部内容，只对非 type="textarea" 有效
prepend	输入框前置内容，只对非 type="textarea" 有效
append	输入框后置内容，只对非 type="textarea" 有效 
-->
<!-- 如果我要使用icon 我可以直接在el-input 中使用 :prefix-icon="Phone" 来添加图标 -->
<!-- 如果我要插入内容可以使用<template #prepend> 来插入内容 -->
              <el-input
                v-model=phoneForm.phone
                placeholder="建议使用常用手机号"
                :prefix-icon="Phone"
              >
              </el-input>
            </div>
          </el-form-item>

          <el-form-item>
            <div class="verification-wrapper">
              <el-input
                v-model=phoneForm.verificationCode
                placeholder="请输入验证码"
                :prefix-icon="Key"
              >
              </el-input>
              <el-button
                type="primary"
                :disabled="isSending || countdown > 0"
                @click="sendVerificationCode"
                class="send-code-btn"
              >
                {{ countdown > 0 ? `${countdown}秒后重试` : '获取验证码' }}
              </el-button>
            </div>
          </el-form-item>

          <el-form-item class="form-item-wrapper">
            <el-button
              type="primary"
              class="next-step-btn"
              :loading="isSubmitting"
              @click="nextToStep2"
              :disabled="!phoneForm.phone || !phoneForm.verificationCode"
            >
              继续
            </el-button>
          </el-form-item>
        </el-form>

      <!-- 步骤2：填写账号信息 -->
      <div v-if="currentStep === 2" class="step-content">
        <el-form ref="accountFormRef" :model="accountForm" :rules="accountRules" class="register-form">
          <el-form-item prop="username" class="form-item-wrapper">
            <el-input
              v-model="accountForm.username"
              placeholder="账户唯一识别用来登录"
              @blur="checkUsernameExists"
              class="account-input"
              :prefix-icon="User"
            />
          </el-form-item>

          <el-form-item prop="password" class="form-item-wrapper">
            <!-- show-password密码的小眼睛功能 -->
            <el-input
              v-model="accountForm.password"
              type="password"
              placeholder="8-16位字母和数字组合"
              class="account-input"
              :prefix-icon="Lock"
              show-password
            />
          </el-form-item>

          <!-- 确认密码输入框 - 修复小眼睛显示 -->
          <el-form-item prop="confirmPassword" class="form-item-wrapper">
            <el-input
              v-model="accountForm.confirmPassword"
              type="password"
              placeholder="请再次输入密码"
              class="account-input"
              :prefix-icon="Lock"
              show-password
            />
          </el-form-item>

          <el-form-item class="form-item-wrapper">
            <el-button
              type="primary"
              class="register-btn"
              :loading="isSubmitting"
              @click="submitRegistration"
              :disabled="!canSubmit"
            >
              立即注册
            </el-button>
          </el-form-item>
        </el-form>
      </div>

      <!-- 步骤3：注册成功 -->
      <div v-if="currentStep === 3" class="step-content">
        <div class="success-container">
          <div class="success-icon">✓</div>
          <h3 class="success-title">注册成功</h3>
          <p class="success-message">
            恭喜您注册成功！<br />
            <span>{{ redirectCountdown }}秒后将自动跳转到首页...</span>
          </p>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, onUnmounted } from 'vue';
import { ElMessage } from 'element-plus';
import { useRouter } from 'vue-router';
import { post, get, type RequestConfig } from '@/utils/request';
import { User, Lock, Phone, Key } from '@element-plus/icons-vue';


// 路由实例
const router = useRouter();
// 步骤控制
const currentStep = ref(1);
const redirectCountdown = ref(3);

// 表单引用
const phoneFormRef = ref();
const accountFormRef = ref();

// 步骤1：手机号表单数据
const phoneForm = reactive({
  phone: '',
  verificationCode: ''
});

// 步骤2：账号信息表单数据
const accountForm = reactive({
  username: '',
  password: '',
  confirmPassword: ''
});

const isPhoneValid = ref(false);
const isSending = ref(false);
const countdown = ref(0);
const isSubmitting = ref(false);

let timer : number | undefined;
let countdownTimer : number | undefined;

// 用户名验证函数
// ### 1. 字符匹配
// - . ：匹配除换行符以外的任意单个字符
// - [abc] ：匹配方括号内的任意一个字符（a、b或c）
// - [^abc] ：匹配除a、b、c以外的任意字符
// - [a-z] ：匹配任意小写字母
// - [A-Z] ：匹配任意大写字母
// - [0-9] ：匹配任意数字
// ### 2. 量词
// - * ：匹配前面的元素零次或多次
// - + ：匹配前面的元素一次或多次
// - ? ：匹配前面的元素零次或一次
// - {n} ：匹配前面的元素恰好n次
// - {n,} ：匹配前面的元素至少n次
// - {n,m} ：匹配前面的元素至少n次，最多m次
// ### 3. 位置匹配
// - ^ ：匹配字符串的开头
// - $ ：匹配字符串的结尾
// - \b ：匹配单词边界
// - \B ：匹配非单词边界
// ### 4. 特殊字符转义
// - \d ：匹配任意数字，等价于 [0-9]
// - \D ：匹配任意非数字，等价于 [^0-9]
// - \w ：匹配任意字母、数字或下划线，等价于 [a-zA-Z0-9_]
// - \W ：匹配任意非字母、数字或下划线，等价于 [^a-zA-Z0-9_]
// - \s ：匹配任意空白字符（空格、制表符、换行符等）
// - \S ：匹配任意非空白字符
// JavaScript中，正则表达式可以通过两种方式创建：
// 1. 1.
//    字面量语法 ：
// ```
// const regex = /pattern/flags;
// ```
// 1. 2.
//    构造函数 ：
// ```
// const regex = new RegExp('pattern', 
// 'flags');
// ```
// 常用的标志（flags）包括：
// - g ：全局匹配
// - i ：忽略大小写
// - m ：多行匹配
// 
const validateUsername = (rule: any, value: string, callback: any) => {
  if (!value) {
    callback(new Error('用户名不能为空'));
  } else if (value.length < 4 || value.length > 16) {
    callback(new Error('用户名长度为4-16位'));
  } else if (!/^[a-zA-Z0-9_]+$/.test(value)) {
    callback(new Error('用户名只能包含字母、数字和下划线'));
  } else {
    callback();
  }
};

// 密码验证函数
const validatePassword = (rule: any, value: string, callback: any) => {
  if (!value) {
    callback(new Error('密码不能为空'));
  } else if (value.length < 8 || value.length > 16) {
    callback(new Error('密码长度为8-16位'));
  } else {
    const hasNumber = /\d/.test(value);
    const hasLetter = /[a-zA-Z]/.test(value);
    if (!hasNumber || !hasLetter) {
      callback(new Error('密码必须同时包含数字和字母'));
    } else {
      callback();
      // 验证密码后，同时验证确认密码
      //rule的作用是用于标识当前验证的字段、支持联动验证、定位错误信息和支持通用验证器。
      //这里的rule是一个对象，里面需要填写field：验证的字段名
      //() => {}这个函数是如何处理的
      if (accountForm.confirmPassword) {
        validateConfirmPassword({ field: 'confirmPassword' }, 
        accountForm.confirmPassword, () => {});
      }
    }
  }
};

// 确认密码验证函数
const validateConfirmPassword = (rule: any, value: string, callback: any) => {
  if (!value) {
//然后，通过调用 callback(error) ，这个 Error 对象被传递给了调用验证器函数的
// 上层代码（通常是 Element Plus 的内部验证机制）。可以在我对应的标签下面显示出来
    callback(new Error('请确认密码'));
  } else if (value !== accountForm.password) {
    callback(new Error('两次输入的密码不一致'));
  } else {
    callback();
  }
};

// 手机号验证函数
const validatePhone = (rule: any, value: string, callback: any) => {
  if (!value) {
    callback(new Error('请输入手机号'));
  } else if (!/^1[3-9]\d{9}$/.test(value)) {
    callback(new Error('请输入正确的手机号码'));
  } else {
    isPhoneValid.value = true;
    callback();
  }
};

// 手机号验证规则
const phoneRules = {
  phone: [
    { validator: validatePhone, trigger: 'blur' }
  ]
};

// 账号信息验证规则
const accountRules = {
  username: [
    { validator: validateUsername, trigger: 'blur' }
  ],
  password: [
    { validator: validatePassword, trigger: 'blur' }
  ],
  confirmPassword: [
    { validator: validateConfirmPassword, trigger: 'blur' }
  ]
};

// 计算是否可以提交注册
const canSubmit = computed(() => {
  return accountForm.username && 
         accountForm.password && 
         accountForm.confirmPassword
});


// 发送验证码
const sendVerificationCode = async () => {
    isPhoneValid.value = await phoneFormRef.value.validate();
  if (!isPhoneValid.value) {
    //手机号码错误的时候不发送验证码
    ElMessage.warning('请输入正确的手机号码');
    return;
  }

  isSending.value = true;
  try {
    // 调用后端发送验证码接口
    await post('/register/sendCode', {
      phone: phoneForm.phone
    },{ showLoading: false } as RequestConfig);
    startCountdown();
  } catch (error) {
    console.error('Send verification code error:', error);
  } finally {
    //最后需要将我的按钮变得可点击
    isSending.value = false;
  }
};

// 开始倒计时
const startCountdown = () => {
  countdown.value = 120;
   timer = setInterval(() => {
    countdown.value--;
    if (countdown.value <= 0) {
      clearInterval(timer);
      timer = undefined;
    }
  }, 1000);
};

// 检查用户名是否已存在
const checkUsernameExists = async () => {
  try{
    //单独对某一个字段验证调用它对应的验证规则
    await accountFormRef.value.validateField('username');
  }catch{
    console.log("用户名校验失败，不进行后端检查");
    return;
  }

  try {
    await get("/register/checkUsername",{username: accountForm.username},
    {showLoading: false} as RequestConfig);
    
  } catch (error) {
    console.error('Check username error:', error);
  }
};
// 下一步：验证手机后进入账号信息填写
const nextToStep2 = async () => {
  if (!phoneFormRef.value) return;
  
  const valid = await phoneFormRef.value.validate();
  if (valid) {
    //提交的加载控制
    isSubmitting.value = true;
    try {
      // 调用后端验证验证码接口
      await post('/register/verifyCode', {
        phone: phoneForm.phone,
        code: phoneForm.verificationCode
      });
      currentStep.value = 2;
    } catch (error) {
      console.error('验证手机验证码失败！！！', error);
    } finally {
      //最后将提交按钮复原为可点击状态
      isSubmitting.value = false;
    }
  }
};

// 提交注册
//以下这种提交的函数流程大致为（是async 和 await组合）
// 1. 首先看我的对应的组件是否存在也就是判断ref.value是否为null
// 2. 然后进行我的表单验证，也就是await ref.value.validate()
// 3. 最后判断我的表单是否通过验证并且我的提交按钮是否可以点击
// 4. 如果验证通过我就将我的表单提交按钮变为不可点击状态
// 一般是:loading=true或者:disabled=true
//5. 然后是调用后端的接口传递我对应的数据，需要使用try catch来处理异常
// 注意有的时候我不需要加载或者显示错误就加上对应的配置参数
//6. 然后是我的其他逻辑
//最后在我的finally中复原我的提交按钮
const submitRegistration = async () => {
  if (!accountFormRef.value) return;
  
  const valid = await accountFormRef.value.validate();
  if (valid && canSubmit.value) {
    isSubmitting.value = true;
    try {
      // 调用后端注册接口
      await post('/register/addUser', {
        phone: phoneForm.phone,
        username: accountForm.username,
        password: accountForm.password
      });
        // 注册成功，进入第三步
        currentStep.value = 3;
        startRedirectCountdown();
    } catch (error) {
      console.error('注册失败！！！', error);
    } finally {
      isSubmitting.value = false;
    }
  }
};

// 开始跳转倒计时
// 使用计时器的方法
// 计时器有两个常用的方法
// 1. setInterval() 方法 他是用来重复执行某个函数的方法
// 2. setTimeout() 方法 他是用来在指定的时间后执行某个函数的方法
// 对于我的使用流程大致为
//1. 首先在开始声明一个let 是一个全局变量用来接收我的计时器的id
//2. 然后是使用我的计时器对于setInterval()方法,在我的函数运行当中一定要有清除的操作
//不然会一直执行下去，清除之后将我的计时器设置为undefined
//3. 最后在我的组件卸载的时候首先判断是否需要清除计时器
// 如果需要则清除我的计时器
const startRedirectCountdown = () => {
  redirectCountdown.value = 3;
  countdownTimer = setInterval(() => {
    redirectCountdown.value--;
    if (redirectCountdown.value <= 0) {
      clearInterval(countdownTimer);
      countdownTimer = undefined;
      router.replace('/home');
    }
  }, 1000);
};
onUnmounted(() => {
  if (timer) {
    clearInterval(timer);
  }
  if (countdownTimer) {
    clearInterval(countdownTimer);
  }
});
</script>

<style scoped>
/* 对于我的所有的输入框最好不要使用max-width,他会导致我输入内容的时候我的框变大变小*/
/* 主要布局调整 */
.register-container {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background-color: #f5f7fa;
  padding: 20px;
}

.register-wrapper {
  width: 100%;
  max-width: 750px;
  background-color: #fff;
  padding: 50px;
  border-radius: 12px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}

.register-title {
  text-align: center;
  margin-bottom: 40px;
  color: #303133;
  font-size: 28px;
  font-weight: 600;
}

/* 步骤指示器样式 */
.step-indicator {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 50px;
  padding: 0 30px;
}

.step-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  flex: 1;
}

.step-number {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background-color: #dcdfe6;
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  margin-bottom: 12px;
  transition: all 0.3s;
  font-size: 16px;
}

.step-text {
  font-size: 16px;
  color: #909399;
  transition: color 0.3s;
}

.step-item.active .step-number {
  background-color: #409eff;
  color: #fff;
}

.step-item.active .step-text {
  color: #409eff;
  font-weight: 500;
}

.step-item.completed .step-number {
  background-color: #67c23a;
  color: #fff;
}

.step-item.completed .step-text {
  color: #67c23a;
}

.step-line {
  flex: 1;
  height: 3px;
  background-color: #dcdfe6;
  margin: 0 15px;
  transition: background-color 0.3s;
}

.step-line.active {
  background-color: #409eff;
}

/* 表单样式 */
.register-form {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}

/* 统一表单项容器样式 - 相对定位，为错误提示的绝对定位做准备 */
.form-item-wrapper {
  width: 450px;
  margin-bottom: 28px;
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  min-height: 80px; /* 确保表单项高度稳定，包含错误信息空间 */
}

/* 手机号输入框容器 */
.phone-input-wrapper {
  display: flex;
  height: 60px;
  border: 1px solid #dcdfe6;
  border-radius: 6px;
  overflow: hidden;
  background-color: #fff;
  width: 450px;
  transition: border-color 0.3s;
}
.phone-input-wrapper :deep(.el-input__wrapper) {
  border: none !important;
  box-shadow: none !important;
  border-radius: 0 !important;
}

/* 确保手机号输入框和验证码区域长度完全一致 */
.phone-input-wrapper,
.verification-wrapper {
  width: 100%;
  max-width: 620px;
}

/* 调整国家代码容器宽度 */
.country-code-container {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 120px;
  padding: 0 15px;
  background-color: #f5f7fa;
  border-right: 1px solid #dcdfe6;
  height: 100%;
}

.country-code {
  color: #606266;
  font-size: 16px;
  font-weight: 500;
}

/* 验证码区域样式 */
.verification-wrapper {
  display: flex;
  gap: 15px;
  align-items: center;
  width: 100%;
  max-width: 620px;
}

/* 账号输入框样式 */
.account-input {
  width: 100%;
  width: 330px;
  height: 60px;
  margin-bottom: 0;
}

/* 图标样式调整 */
:deep(.el-input__prefix) {
  display: flex;
  align-items: center;
  justify-content: center;
  left: 15px;
  color: #909399;
  height: 100%;
}

:deep(.el-input__prefix-inner) {
  display: flex;
  align-items: center;
  justify-content: center;
}

:deep(.el-input__prefix .el-icon) {
  font-size: 20px;
}

/* 调整输入框内边距和字体大小 */
:deep(.el-input__inner) {
  padding-left: 50px;
  padding-right: 50px;
  font-size: 18px;
}

/* 按钮样式 */
.send-code-btn {
  width: 140px;
  height: 60px;
  font-size: 18px;
  border-radius: 6px;
}

.next-step-btn,
.register-btn {
  width: 300px;
  max-width: 620px;
  height: 60px;
  font-size: 20px;
  background-color: #ff6700;
  border-color: #ff6700;
  margin-top: 15px;
  border-radius: 6px;
  font-weight: 500;
}

.next-step-btn:hover,
.register-btn:hover {
  background-color: #ff7a23;
  border-color: #ff7a23;
}

/* 聚焦效果 */
.phone-input-wrapper:focus-within {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

:deep(.el-input__wrapper:focus-within) {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

/* 确保所有步骤内容居中 */
.step-content {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  width: 100%;
}

/* 成功页面样式 */
.success-container {
  text-align: center;
  padding: 80px 0;
}

.success-icon {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  background-color: #67c23a;
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 64px;
  font-weight: bold;
  margin-bottom: 30px;
}

.success-title {
  font-size: 32px;
  color: #303133;
  margin-bottom: 25px;
}

.success-message {
  font-size: 18px;
  color: #606266;
  line-height: 1.8;
}

.success-message span {
  color: #409eff;
}

/* 错误状态样式 - 确保错误状态优先级高于聚焦状态 */
.el-form-item.is-error .phone-input-wrapper {
  border-color: #f56c6c !important;
  box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.2) !important;
}

.el-form-item.is-error .country-code-container {
  border-color: #f56c6c !important;
}

:deep(.el-form-item.is-error .el-input__wrapper) {
  border-color: #f56c6c !important;
  box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.2) !important;
  height: 60px !important;
  min-height: 60px !important;
}

/* 确保错误状态下聚焦时不显示蓝色 */
.el-form-item.is-error .phone-input-wrapper:focus-within {
  border-color: #f56c6c !important;
  box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.2) !important;
}

:deep(.el-form-item.is-error .el-input__wrapper:focus-within) {
  border-color: #f56c6c !important;
  box-shadow: 0 0 0 2px rgba(245, 108, 108, 0.2) !important;
}

/* 确保错误状态下输入框大小不变的关键样式 */
:deep(.el-input) {
  height: 60px !important;
  min-height: 60px !important;
  box-sizing: border-box !important;
}

:deep(.el-input__wrapper) {
  height: 60px !important;
  min-height: 60px !important;
  box-sizing: border-box !important;
}

:deep(.el-input__inner) {
  height: 100% !important;
  box-sizing: border-box !important;
}

/* 确保小眼睛图标显示的样式 */
:deep(.el-icon-view) {
  display: inline-block;
}
</style>